#ifndef REGISTER_HPP
#define REGISTER_HPP

#include <QObject>
#include <QMutex>
#include <QMutexLocker>
#include <math.h>
#include <limits.h>

/**
* @brief
*
* @class Register register.hpp "register.hpp"
*/
class Register : public QObject
{
    Q_OBJECT

public:    
    /**
    * @brief Default Constructor
    *
    * @fn Register
    * @param address
    * @param bank
    */
    explicit Register(int address, int bank, int standard = 0);

    ~Register();

    /**
    * @brief Set a single Bit
    *
    * @fn setBit
    * @param bit
    */
    virtual void setBit(int bit);

    /**
    * @brief Clear a single Bit
    *
    * @fn clearBit
    * @param bit
    */
    virtual void clearBit(int bit);

    /**
    * @brief Check whether a specified bit is set
    *
    * @fn isSet
    * @param bit
    * @return bool
    */
    bool isSet(int bit) const;

    /**
    * @brief Set the complete value for this Register
    *
    * @fn setValue
    * @param value
    */
    virtual void setValue(int value, bool force = false);

    /**
    * @brief Get the complete value for this Register
    *
    * @fn getValue
    * @return int
    */
    int getValue() const;

    /**
    * @brief Returns the bank of this Register
    *
    * @fn getBank
    * @return int
    */
    const int getBank() const;

    /**
    * @brief Returns the Address of this Register
    *
    * @fn getAddress
    * @return int
    */
    const int getAddress() const;

    /**
    * @brief Clear the Register
    *
    * @fn clear
    */
    virtual void clear();

    /**
    * @brief Sets the Register to a standard value
    *
    * @fn reset
    */
    virtual void reset();

    Register& operator++(int);

    Register& operator--(int);

    Register& operator<<(int digits);

    Register& operator>>(int digits);

    Register& operator+=(int value);

    Register& operator-=(int value);

    Register& operator&=(int value);

    Register& operator|=(int value);

    Register& operator^=(int value);

    bool operator==(int value);

    bool operator==(Register &reg);

    Register& operator+(int value);

    Register& operator-(int value);

    Register& operator&(int value);

    Register& operator|(int value);

    Register& operator^(int value);

    Register& operator=(int value);

    /**
    * @brief Get a textual representation of the internal value
    * @details If bit is not in the range 0-7, the complete value is returned as string
    * Otherwise only the specified bit is returned as String
    *
    * @fn toString
    * @param bit
    * @return QString
    */
    QString toString(int bit = -1) const;

protected:
    int value;
    const int standard;
    const int address;
    const int bank;
    QMutex *mutex;

signals:
    /**
    * @brief Signal is emitted when the internal data has changed
    *
    * @fn contentChanged
    * @param value
    */
    void contentChanged(int value);

    /**
    * @brief Signal is emitted when intenal data changed
    * @details address and bank representing the location of this Register
    *
    * @fn changed
    * @param address
    * @param bank
    */
    void changed(int address, int bank);

    void registerOverflow();
    void registerUnderflow();

};

#endif // REGISTER_HPP
